先說結論:不是所有 AI 工作負載都需要 Kubernetes。
如果今天只有一台主機、一個模型、一個使用者,Docker Compose 甚至一個 Python process 就可能已經夠用。這種情況硬上 Kubernetes,通常只是把簡單問題變複雜。
但當場景開始變成:
問題就不再只是「Container 能不能跑」,而是:
哪個工作應該跑在哪裡?誰可以用哪張 GPU?GPU 不夠時誰先跑?Pod 掛掉後誰負責恢復?模型還沒載完時為什麼不能對外宣告 Ready?
這些才是 Kubernetes 開始有價值的地方。
所以這 30 天,我不會把 Kubernetes 當成「部署 AI 的潮流工具」,而是把它當成一套治理複雜工作負載的控制系統。
一般 Web 服務常見的資源是 CPU 與 Memory。
AI workload 多了一個特別麻煩的資源:GPU。
GPU 有幾個特性,會讓排程問題變得比一般服務更難:
因此,AI 平台真正需要的是:
工作負載
↓
資源宣告
↓
排程
↓
隔離 / 優先級
↓
服務與健康檢查
↓
觀測
↓
失敗恢復
而 Kubernetes 恰好提供了這條控制鏈的大部分基礎能力。
Kubernetes 本身不會突然知道某台 Node 上有幾張 NVIDIA 或 AMD GPU。
官方文件的做法是透過 Device Plugin 把特殊硬體資源暴露給 Kubernetes。安裝對應 driver 與 vendor device plugin 之後,Node 會出現像這樣的 schedulable resource:
nvidia.com/gpu
Pod 就可以在資源需求裡宣告:
apiVersion: v1
kind: Pod
metadata:
name: gpu-demo
spec:
containers:
- name: app
image: example/ai-app:latest
resources:
limits:
nvidia.com/gpu: 1
這個 YAML 很短,但背後其實代表了一個重要改變:
GPU 從「某台機器上的硬體」,變成「可以被叢集排程器理解的資源」。
Kubernetes 官方目前對 GPU custom resource 的限制也很明確:GPU 通常以 limits 宣告,不能只寫 GPU requests;如果同時寫 request 與 limit,兩者必須相等。
這也直接帶出本系列後面會一直碰到的問題:
nvidia.com/gpu: 1代表「一張 GPU」,但它並不直接等於「我要 8 GB VRAM」。
GPU sharing、MIG、MPS、time-slicing 以及不同工作負載之間的隔離,都是後續真正需要處理的工程問題。
Kubernetes 排程 CPU / Memory 時,核心概念是 request。
Scheduler 會根據 Node capacity 與既有 Pod 的 request,決定新 Pod 能不能被放進去;即使某台 Node 當下實際使用率很低,只要宣告的 request 已經把容量占滿,Scheduler 仍可能拒絕排程。
這個設計對 AI 特別重要。
因為我們最不希望看到的是:
「平常看起來沒事,所以多塞幾個服務;流量一上來,所有 workload 一起搶資源。」
Kubernetes 的價值不是把硬體變多,而是逼我們把「誰需要多少資源」這件事寫進系統規則裡。
但 GPU 也讓這件事更棘手。CPU 可以寫 500m,Memory 可以寫 4Gi,GPU 卻不一定能用同樣直覺的粒度切割。
所以後面我會實際比較:
以及不同方式對 isolation、utilization、latency 的影響。
問題不是 Docker 不好,而是它解決的層次不同。
Container 解決的是:
我要如何把應用與依賴包起來,讓它可以一致地執行?
Kubernetes 多處理的是:
當有很多 Container、很多 Node、很多資源限制與很多失敗情境時,整體應該怎麼被管理?
假設今天叢集裡有:
LLM Serving
Embedding Service
ASR
Batch Job
Database Side Service
Monitoring Stack
很快就會出現這些問題:
這些不是一個 docker run 指令本身要解決的問題。
這個系列會把重點放在六件事:
用 Label、NodeSelector、Affinity、Taints / Tolerations,把 workload 送到正確 Node。
讓線上 inference、Embedding、ASR 與 Batch Job 不要互相拖垮。
GPU 不夠時,不是所有 workload 都同等重要。PriorityClass、Preemption 與 Queue policy 會成為關鍵。
Pod 掛掉、Node 掛掉或服務不健康時,系統應該能自動重建,而不是靠人登入主機重啟。
從 Pod / Node 一路看到 GPU、request latency、queue、throughput 與 error。
今天能跑的設定,明天也要能重建;版本升級失敗時,要能回到上一個已知狀態。
如果 Day 30 的成果只是:
「我成功在 Kubernetes 跑了一個 LLM。」
那其實不值得寫 30 天。
真正想驗證的是:
同一個 AI workload
↓
不同排程策略
不同 sharing 策略
不同 priority
不同 health check
不同 autoscaling / recovery 設計
↓
Latency / Throughput / GPU Utilization / Failure Behavior
我會刻意做一些「壞事」:
因為只有在這些情況下,才能看出 Kubernetes 到底是在幫忙,還是只是多了一層複雜度。
Kubernetes 不是 AI 的必要條件,也不是為了「看起來像 Production」。
它真正有價值的地方,是當 AI workload 開始出現多節點、多 GPU、多服務、多使用者與故障恢復需求之後,讓我們可以把資源、排程與生命週期變成可描述、可執行、可觀測的規則。
Kubernetes 不是為了炫技,而是為了治理複雜工作負載。
明天我會先把這個系列的 GPU Kubernetes 參考架構畫清楚:Node、Runtime、Storage、Model Serving 與 Observability 各自放在哪裡,以及哪些東西其實不該一開始就塞進 cluster。
下一篇:Day 02|GPU Kubernetes 參考架構:節點、Runtime、Storage 與 Serving
本系列以自建、可公開的測試環境驗證設計,不公開任何內部網路、帳號或未公開的實際部署資訊。